/**
 * JAVACC DEMO 1.0
 */
package com.apache.passport.service.plugins;

import com.apache.api.vo.ParamsVo;
import com.apache.api.vo.ResultEntity;
import com.apache.database.constant.SpringContextLoader;
import com.apache.database.constant.SystemTools;
import com.apache.database.constant.Validator;
import com.apache.database.db.IDao;
import com.apache.database.model.MethodParam;
import com.apache.passport.common.DesUtils;
import com.apache.passport.common.LoginCacheErrTimer;
import com.apache.passport.common.PassPortConst;
import com.apache.passport.common.PassportHelper;
import com.apache.passport.entity.*;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * description:  外部系统登录(socket形式,webservice)
 * 此种方式只返回token,下次手机端放的时候,都需要写到token进行传输
 * 例如,手机客户端,c#界面登录,以及其他语言的登录,全部使用这种形式或webservice
 * 2015年5月5日11:07:28  外部系统登录时,添加账户锁定及删除校验
 *
 * @author Hou Dayu 创建时间：2016-12-25
 */
public class OutSideSysLoginPlugin extends SuperPluginConnector {

    protected IDao blackRosterDao;

//    protected IDao uctUserDao;

    private DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");

//    public void setUctUserDao(IDao uctUserDao) {
//        this.uctUserDao = uctUserDao;
//    }

    /**
     * TODO 例如手机客户端,C# 等语言的登录
     * 下次手机端放的时候,都需要写到token进行传输
     *
     * @see com.apache.api.manager.PluginConnector#execute(ParamsVo)
     */
    @Override
    public Object execute(ParamsVo vo) throws Exception {
        String addressIP = String.valueOf(vo.getParams("addressIP"));
        ResultEntity result = new ResultEntity();
        result.setResult("true");
        boolean isCheckPassFlag = true;//默认必须校验密码
        if("F".equals(String.valueOf(vo.getParams("isCheckPass")))){//参数=F表示不判断，客户端需验证其他（比如手机短信验证码）
            isCheckPassFlag = false;
        }
        String userEname = (String) vo.getParams("userEname");
        if (Validator.isEmpty(userEname)) {
            result.setEntity("F");
            result.setMessage("用户名不能为空");
            return result;
        }
        String upass = (String) vo.getParams("userPass");
        if (isCheckPassFlag && Validator.isEmpty(upass)) {
            result.setEntity("F");
            result.setMessage("密码不能为空");
            return result;
        }
        ParamsVo<UctUser> vos = new ParamsVo<UctUser>();
        vos = vo;
        //登录前首先从数据库中查询下该用户是否存在于黑名单中
        BlackRoster br = (BlackRoster) getBrInfoByIp(vo);
        if (!Validator.isEmpty(br)) {
            LonErrToken token = new LonErrToken();
            token.setLoginCount("12");
            token.setLoginTime(br.getBrCreatetime());
            //2015年1月29日13:04:07 将用户名添加到错误token中
            token.setUserEname(vos.getObj().getUserEname());
            token.setCacheId(addressIP + br.getBrAccount());
            //存储缓存
            PassPortConst.setLonErrToken(addressIP, br.getBrAccount(), token);
            result.setEntity("F");
            result.setMessage("账户已被锁定");
            return result;
        }
        UctUser obj = (UctUser) getInfoByEname(userEname);
        if (!Validator.isEmpty(obj)) {
            //判断密码是否正确
            if (isCheckPassFlag && !(obj.getUserPass()).equalsIgnoreCase(upass)) {
                result.setEntity("F");
                //			result.setMessage("用户不存在");
                result.setMessage("用户名或密码错误");
                LoginCacheErrTimer.getInstance().setErrToken(vos, addressIP, br, obj);
                return result;
            }
            //if ((obj.getUserPass()).equalsIgnoreCase(upass)) {

            String delStatus = obj.getDelStatus();// 删除状态(F:未删除,T:假删除)
            Integer userStatus = obj.getUserStatus();//用户状态(-1:删除状态,0:停用,1:启用)

            if (Validator.isEmpty(userStatus)) {
                userStatus = 10000;//自定值,防止用户状态未设置
            }
            if (Validator.isEmpty(delStatus)) {
                delStatus = "E";//自定值,防止用户删除状态为设置
            }

            if (userStatus == 10000 || "E".equals(delStatus)) {
                result.setEntity("F");
                result.setMessage("用户状态异常,请联系系统管理员");
                return result;
            }

            if ("T".equals(delStatus) || userStatus == -1) {
                result.setEntity("F");
                result.setMessage("用户已留痕删除,请联系系统管理员");
                return result;
            }

            if (userStatus == 0) {
                result.setEntity("F");
                result.setMessage("用户已停用,请联系系统管理员");
                return result;
            }

            //虽然密码正确,但是需要判断下之前缓存中是否存在该用户的登陆错误信息,如果存在,则依然返回等待
            LonErrToken tokenE = PassPortConst.getLonErrToken(addressIP, obj.getUserEname());
            if (!Validator.isEmpty(tokenE)) {
                if(LoginCacheErrTimer.getInstance().checkErrToken(addressIP,obj.getUserEname())){
                    String count = tokenE.getLoginCount();
                    int c = Integer.parseInt(count);
                    if ("3".equals(tokenE.getLoginCount()) || "6".equals(tokenE.getLoginCount())
                            || "9".equals(tokenE.getLoginCount()) || c > 12) {
                        //如果错误次数等于以上几个参数,也同样需要校验下时间是否已经过期,防止时间已过,且登录密码正确,却一直没有更新缓存
                        //setErrToken(vo, remoteIp, br, obj);
                        LoginCacheErrTimer.getInstance().setErrToken(vos, addressIP, br, obj);
                        result.setEntity("F");
                        result.setMessage("账户已被锁定");
                        return result;
                    }
                }
            }

            String randNum = PassportHelper.getInstance().createRandomString(12);
            Token token = new Token();
            String tokenId = com.apache.cache.util.Validator.generate() + randNum;
            String db_userEname = obj.getUserEname();
            token.setTokenId(tokenId);
            token.setUserEname(DesUtils.getInstance().encrypt(db_userEname));
            token.setUserCname(obj.getUserCname());
            token.setLoginTime(df.format(new Date()));
            token.setEmail(DesUtils.getInstance().encrypt(obj.getEmail()));
            token.setMobile(DesUtils.getInstance().encrypt(obj.getMobile()));
            token.setUserId(obj.getUserId());
            result.setEntity(token);
            result.setMessage("登录成功");
            LoginInfo loginInfo = new LoginInfo();
            loginInfo.setLgnLastipaddress(addressIP);
            loginInfo.setUserEname(db_userEname);
            token.setLoginInfo(loginInfo);
            token.setCustomerType(obj.getCustomerType());
            token.setUserLevel(obj.getUserLevel());
            token.setUserType(obj.getUserType());
            //token.setRegSource(obj.getRegSource());

            PassPortConst.detLonErrToken(addressIP, obj.getUserEname());

            String synFlag = SystemTools.getInstance().getValue("synFlag");
            PassPortConst.setToken("1".equals(synFlag) ? true : false, tokenId, token);
            return result;
        } else {
            result.setEntity("F");
            result.setMessage("用户不存在");
//                result.setMessage(StrUtil.doNull(checkErrorToken(addressIP, obj), "用户名或密码错误"));
//                LoginCacheErrTimer.getInstance().setErrToken(vos, addressIP, br, obj);
            return result;
        }
        // } else {

//        }
    }

    private String checkErrorToken(String remoteIp, UctUser user) {
        //插件中存了错误次数,则在此判断
        LonErrToken token = PassPortConst.getLonErrToken(remoteIp, user.getUserEname());
        String msg = "";
        if (!Validator.isEmpty(token)) {
            String errCount = token.getLoginCount();
            String mim = token.getMim();
            int count = Integer.parseInt(errCount);
            String[] params = { mim };
            if (3 == count) {
                msg = SpringContextLoader.getMessage("zh_CN", "login_err_3", params, "");
            } else if (6 == count) {
                msg = SpringContextLoader.getMessage("zh_CN", "login_err_6", params, "");
            } else if (9 == count) {
                msg = SpringContextLoader.getMessage("zh_CN", "login_err_9", params, "");
            } else if (12 == count) {
                msg = SpringContextLoader.getMessage("zh_CN", "login_err_12", params, "");
            } else {
                msg = "您已登录错误" + errCount + "次,请在认真填写登录信息";
            }
        }
        return msg;
    }

    /**
     * description:  根据ename查询用户信息
     */
    public Object getInfoByEname(String userEname) {
        return super.getUserByEname(userEname);
    /*
        if (Validator.isNull(userEname)) {
            return null;
        }
        String sql = uctUserDao.getSql(3);// from UctUser where userEname :=userEname

        String mobileLogin = SystemTools.getInstance().getValue("mobileLogin");
        String emailLogin = SystemTools.getInstance().getValue("emailLogin");

        if ("1".equals(mobileLogin)) {
            sql += "or mobile :=userEname ";
        }
        if ("1".equals(emailLogin)) {
            sql += "or email :=userEname ";
        }

        MethodParam param = new MethodParam("ByUserEname", "", sql,
                "com.apache.passport.entity.UctUser");
        param.setParams("userEname", userEname);
        if ("1".equals(mobileLogin)) {
            param.setParams("mobile", userEname);
        }
        if ("1".equals(emailLogin)) {
            param.setParams("email", userEname);
        }
        return uctUserDao.selectSingle(param);
        */
    }

    /**
     * description:  根据IP及用户名获取黑名单
     *
     * @param vo
     * @return
     */
    public Object getBrInfoByIp(ParamsVo<UctUser> vo) {
        String remoteIp = (String) vo.getParams("remoteIp");
        String userEname = (String) vo.getParams().get("userEname");
        //只验证用户名
        String sql = blackRosterDao.getSql(4);
        if (!Validator.isNull(remoteIp)) {
            sql += " and brIpaddress :=brIpaddress ";
        }
        MethodParam param = new MethodParam("ByIpOrUserEname", "", sql,
                BlackRoster.class.getName());
        param.setParams("brIpaddress", remoteIp);
        param.setParams("brAccount", userEname);
        return blackRosterDao.selectSingle(param);
    }

    public void setBlackRosterDao(IDao blackRosterDao) {
        this.blackRosterDao = blackRosterDao;
    }
}
